/*
 * GSMCardUtils.java
 * This class contains methods which help to converts data form SIM cards
 *
 * Created on 22. Januar 2007, 13:22
 *
 *  This file is part of JSmex.
 *
 *  JSmex is free software; you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation; either version 2 of the License, or
 *  (at your option) any later version.
 *
 *  JSmex is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with Foobar; if not, write to the Free Software
 *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 *
 */

package jsmex.function;

import java.nio.ByteBuffer;
import java.nio.CharBuffer;
import java.nio.charset.CharsetEncoder;
import jsmex.JSmexTools;
import net.freeutils.charset.GSMCharset;

/**
 *
 * @author CardContact (http://www.cardcontact.de) modified by Tobias Senger
 */
public class GSMCardUtils {
    
    
    // Converts a char array containing BCD coded phone number to String
    public static String decodePhoneNumber(byte [] buf) {
        byte value, low, high;
        int j,k;
        byte[] tempfield = new byte[buf.length * 2];
        byte[] tnumber;
        
        k = 0;
        
        value = (byte) buf[0];
        
        if (value == (byte) 0x91)
            tempfield[k++] = (byte)'+';
        
        if (value == (byte) 0xff)
            return new String();
        
        j = 1;
        
        while (j < buf.length) {
            value = (byte) buf[j];
            
            low = (byte) ((value >> 4) & (byte) 0x0f);
            high = (byte) (value & (byte) 0x0f);
            
            if (high == (byte) 0x0f)
                break;
            tempfield[k++] = toAsciiFromDecimal(high);
            
            if (low == (byte) 0x0f)
                break;
            tempfield[k++] = toAsciiFromDecimal(low);
            
            j++;
        }
        
        tnumber = new byte[k];
        System.arraycopy(tempfield, 0, tnumber, 0, k);
        
        return new String(tnumber);
    }
    
    
    // Converts a given phone number String to a char array using BCD notation
    public static byte [] codePhoneNumber(String buf) {
        byte low, high;
        int k, i, l;
        byte[] temp;
        byte[] tmp;
        
        buf.trim();
        if (buf.length() == 0)
            return null;
        
        l = ((buf.length() / 2) + (buf.length() % 2)) + 1;
        
        k = 0; i = 0;
        
        tmp = new byte[l];
        
        temp = buf.getBytes();
        
        low = toDecimalFromAscii(temp[k]);
        
        if(low == '+') {
            tmp = new byte[l - (buf.length() % 2)];
            tmp[i++] = (byte) 0x91;
            k++;
        } else  {
            tmp[i++] = (byte) 0x81;
        }
        
        
        while (k < buf.length()) {
            low  = toDecimalFromAscii(temp[k++]);
            if (k < buf.length())
                high = toDecimalFromAscii(temp[k++]);
            else
                high = (char) 0x0f;
            
            tmp[i++] = (byte) ((high << 4) | low);
        }
        
        return tmp;
    }
    
    
    // Converts a given name String to a char array
    public static byte [] codeName(String buf, int lengthOfAlphaID) {
        int i, k;
        int length, diff;
        
        if (buf.length() == 0)
            return null;
        
        if (buf.length() > lengthOfAlphaID)
            length = lengthOfAlphaID;
        else
            length = buf.length();
        
        diff = lengthOfAlphaID - length;
        
        
        byte [] tmpfield = new byte[lengthOfAlphaID];
        
        GSMCharset gsmCharset = new GSMCharset();
        CharsetEncoder enc = gsmCharset.newEncoder();
        ByteBuffer bb = gsmCharset.encode(buf);
        
        
        for (i=0;i<length;i++) {
            tmpfield[i] = bb.get(i);
        }
        
        k = 0;
        while (k < diff) {
            tmpfield[i+k] = (byte) 0xff;
            k++;
        }
        
        return tmpfield;
    }
    
    
    
    // Converts a char array containing coded entry name to String
    public static String decodeName(byte [] buf) {
        int j, index;
        byte [] tempfield;
        byte help;
        
        index = 0;
        
        GSMCharset gsmCharset = new GSMCharset();
        ByteBuffer bb = ByteBuffer.wrap(buf);
        CharBuffer cb = gsmCharset.decode(bb);
        String name = cb.toString();
        return name.replace('\ufffd',' ').trim();
    }
    
    
    // Convert a ASCII character to a decimal value
    public static byte toDecimalFromAscii(byte v) {
        byte tmp = v;
        
        switch(v) {
            case (byte) '0':  tmp = 0;
            break;
            case (byte) '1':  tmp = 1;
            break;
            case (byte) '2':  tmp = 2;
            break;
            case (byte) '3':  tmp = 3;
            break;
            case (byte) '4':  tmp = 4;
            break;
            case (byte) '5':  tmp = 5;
            break;
            case (byte) '6':  tmp = 6;
            break;
            case (byte) '7':  tmp = 7;
            break;
            case (byte) '8':  tmp = 8;
            break;
            case (byte) '9':  tmp = 9;
            break;
        }
        return tmp;
    }
    
    // convert decimal value to ASCII character
    public static byte toAsciiFromDecimal(byte v) {
        byte tmp = v;
        
        switch(v) {
            case 0:  tmp = (byte) '0';
            break;
            case 1:  tmp = (byte) '1';
            break;
            case 2:  tmp = (byte) '2';
            break;
            case 3:  tmp = (byte) '3';
            break;
            case 4:  tmp = (byte) '4';
            break;
            case 5:  tmp = (byte) '5';
            break;
            case 6:  tmp = (byte) '6';
            break;
            case 7:  tmp = (byte) '7';
            break;
            case 8:  tmp = (byte) '8';
            break;
            case 9:  tmp = (byte) '9';
            break;
        }
        return tmp;
    }
    
    /**
     * This function converts GSM 3.38 charakters to Unicode characters.
     * @param b 
     * @return String 
     */
    
    public static char byteToChar(byte b){
        byte[] temp = new byte[1];
        temp[0] = b;
        String s = decodeName(temp);
        return s.charAt(0);
    }
    
}
